//
// Created by Hi on 25-10-27.
//

#include "multiheader.h"
#include <QStandardItemModel>

MutilHeader::MutilHeader(Qt::Orientation orientation, QWidget *parent)
    : QHeaderView(orientation, parent)
{

    QStandardItemModel* pDefModel = new QStandardItemModel(this);
    setModel(pDefModel);
    connect(this, SIGNAL(sectionResized(int, int, int)), this, SLOT(onSectionResized(int, int, int)));
}

MutilHeader::~MutilHeader()
{

}

void MutilHeader::setLabels(const QList<QStringList>& headers)
{
    QAbstractItemModel* pModel = model();
    if (pModel == nullptr)
    {
        return;
    }

    int nRowCount = headers.size();
    pModel->insertRows(0, nRowCount);
    if (nRowCount > 0)
    {
        int nColCount = headers[0].size();
        pModel->insertColumns(0, nColCount);
    }

    // 设置列头文字
    for (int i = 0; i < nRowCount; ++i)
    {
        int nColCount = headers[i].size();
        for (int j = 0; j < nColCount; ++j)
        {
            QModelIndex index = pModel->index(i, j);
            pModel->setData(index, QVariant(headers[i][j]), Qt::DisplayRole);
        }
    }
}

void MutilHeader::setRowHeight(int hight)
{
    _rowHight = hight;
}

void MutilHeader::setSpanRange(const SpanRange& range)
{
    QAbstractItemModel* pModel = model();
    if (pModel == nullptr)
    {
        return;
    }

    // 记录列头合并信息
    QModelIndex index = pModel->index(range.startRow, range.startCol);
    pModel->setData(index, QVariant::fromValue<SpanRange>(range), Qt::UserRole + 20);

    for (int i = range.startRow; i <= range.endRow; ++i)
    {
        for (int j = range.startCol; j <= range.endCol; ++j)
        {
            QModelIndex index = pModel->index(i, j);
            pModel->setData(index, QVariant::fromValue<SpanRange>(range), Qt::UserRole + 20);
        }
    }
}

void MutilHeader::paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const
{
    if (!rect.isValid())
        return;

    QStyleOptionHeader opt;
    QPointF oldBO = painter->brushOrigin();

    initStyleOption(&opt);

    QBrush oBrushButton = opt.palette.brush(QPalette::Button);
    QBrush oBrushWindow = opt.palette.brush(QPalette::Window);

    initStyleOption(&opt);
    // initStyleOptionForIndex(&opt, logicalIndex);
    // We set rect here. If it needs to be changed it can be changed by overriding this function
    opt.rect = rect;

    QBrush nBrushButton = opt.palette.brush(QPalette::Button);
    QBrush nBrushWindow = opt.palette.brush(QPalette::Window);

    // If relevant brushes are not the same as from the regular widgets we set the brush origin
    if (oBrushButton != nBrushButton || oBrushWindow != nBrushWindow) {
        painter->setBrushOrigin(opt.rect.topLeft());
    }

    QAbstractItemModel* pModel = model();
    if (pModel != nullptr)
    {
        int top = opt.rect.top();
        for (int i = 0; i < pModel->rowCount(); ++i)
        {
            QModelIndex index = pModel->index(i, logicalIndex);
            SpanRange range = pModel->data(index, Qt::UserRole + 20).value<SpanRange>();
            if (range.isValid())
            {
                int leftOffset = 0;
                int width = 0;

                for (int j = range.startCol; j <= range.endCol; ++j)
                {
                    int curColWidth = sectionSize(j);
                    if (j < logicalIndex)
                    {
                        leftOffset -= curColWidth;
                    }
                    width += curColWidth;
                }

                int topOffset = 0;
                if (i != range.startRow)
                {
                    topOffset = (range.startRow - i) * _rowHight;
                }

                if (logicalIndex == range.startRow && i == range.startRow)
                {
                    opt.text = pModel->data(index, Qt::DisplayRole).toString();
                }
                else
                {
                    QModelIndex first = pModel->index(range.startRow, range.startCol);
                    opt.text = pModel->data(first, Qt::DisplayRole).toString();
                }

                opt.rect = rect;
                int heightCount = range.endRow - range.startRow + 1;
                opt.rect.setTop(top + _rowHight * i + topOffset);
                opt.rect.setLeft(opt.rect.left() + leftOffset);
                opt.rect.setBottom(opt.rect.top() + _rowHight * heightCount - 1);
                opt.rect.setWidth(width);
                opt.textAlignment = Qt::AlignCenter;
                style()->drawControl(QStyle::CE_Header, &opt, painter, this);
            }
            else
            {
                opt.rect = rect;
                opt.text = pModel->data(index, Qt::DisplayRole).toString();
                opt.rect.setTop(top + _rowHight * i);
                opt.rect.setBottom(top + _rowHight * (i + 1) - 1);
                opt.textAlignment = Qt::AlignCenter;
                style()->drawControl(QStyle::CE_Header, &opt, painter, this);
            }
        }
    }
    else
    {
        opt.textAlignment= Qt::AlignCenter;
        style()->drawControl(QStyle::CE_Header, &opt, painter, this);
    }
    // draw the section.

    painter->setBrushOrigin(oldBO);
}

QSize MutilHeader::sectionSizeFromContents(int logicalIndex) const
{
    QAbstractItemModel* pModel = model();
    if (pModel != nullptr)
    {
        int count = pModel->rowCount();
        QSize size = QHeaderView::sectionSizeFromContents(logicalIndex);
        return QSize(size.width(), _rowHight * count);
    }

    return QHeaderView::sectionSizeFromContents(logicalIndex);
}

void MutilHeader::onSectionResized(int logicalIndex, int oldSize, int newSize)
{
    viewport()->update();
}